//: src/com/silvtar/net/NetTransporterServer.java
/* 
 * Created by 朴晟宁 <piaosn@gmail.com> on 6/3/2013. 
 * Copyright (c) 2013 朴晟宁. All rights reserved.
 * 
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program;
 * 
 * *********************************************************************
 * 
 * Modify History:
 * Date        Version    Description
 * 6/ 3/2013   0.1        Create The Class
 */

package com.silvtar.net.transporter;

import java.io.File;
import java.net.InetAddress;
import java.net.Socket;

import org.apache.commons.net.nntp.NewGroupsOrNewsQuery;

import com.silvtar.io.StreamToolkit;
import com.silvtar.io.StreamTransporter;
import com.silvtar.net.Message;
import com.silvtar.net.NetPack;
import com.silvtar.net.Server;

/**
 * 内置文件传输服务器类。工作良好。
 * 
 * @author 朴晟宁/Silvtar
 * @author piaosn@gmail.com
 * @version 0.1
 */
public class FileTransporterServer implements Server.Acceptor {

    Server cmdServer;
    int    commandPort;
    int    dataPort;

    // --------------------------------构造方法---------------------------------
    /**
     * 
     * @param commandPort
     *            命令通道端口
     * @param dataPort
     *            数据通道端口
     */
    public FileTransporterServer(int commandPort, int dataPort) {

        this.commandPort = commandPort;
        this.dataPort = dataPort;
        
    }

    // --------------------------------构造方法---------------------------------

    public void startCmdServer() {

        // 打开命令端口。
        if (cmdServer == null) {
            cmdServer = new Server(this, commandPort);
        }

        // 开始监听，等待接收方连接。
        cmdServer.listen();
    }

    /**
     * 会被服务器类回调的函数。当接收方通过数据传送连接连接到数据传送服务器时本类即被调用
     * 
     * 我突然间理解了为什么回调的都是类。因为每个类只能被回调一次。而想要多次回调，就需要把不同的功能分开到不同的类中
     */
    @Override
    public void accept(int identifier) {
        
        // 命令通道
        Socket cmdSocket = cmdServer.getSocketList().get(identifier);
        StreamToolkit cmdST = new StreamToolkit(cmdSocket);
        
        // 读取消息
        Message tranFileInfo = (Message) cmdST.readObject();
        

        
        // 如果传输类型为上传(对于服务端为下载)
        if (tranFileInfo.getType() == Message.UPLOAD) {
            // 数据通道
            Socket dataSocket = NetPack.connect(cmdSocket.getInetAddress(), dataPort);
            StreamToolkit dataST = new StreamToolkit(dataSocket);
            File file = new File(tranFileInfo.getContent());
            
            // 判断目录是否存在
            if (!file.getParentFile().exists()) {
                file.getParentFile().mkdirs();
            }
            
            // 开始传输
            StreamTransporter.transStream(dataST.getInputStream(), file);
            cmdST.writeObject(new Message("success", Message.RESULT));
        }
        
        //如果传输类型为下载(对于服务端为上传)
        else if (tranFileInfo.getType() == Message.DOWNLOAD) {
            File file = new File(tranFileInfo.getContent());
            
            // 判断文件是否存在
            if (!file.exists()) {
                cmdST.writeObject(new Message("fail", Message.RESULT));
                return;
            }
            //数据通道
            Socket dataSocket = NetPack.connect(cmdSocket.getInetAddress(), dataPort);
            StreamToolkit dataST = new StreamToolkit(dataSocket);
            
            //开始传输
            StreamTransporter.transStream(file, dataST.getOutputStream());
            cmdST.writeObject(new Message("success", Message.RESULT));
        }
        
        // 如果消息为命令
        else if (tranFileInfo.getType() == Message.COMMAND) {
            // ls命令
            if (tranFileInfo.getContent().equals("ls")) {
                File folder = new File((String) tranFileInfo.getAccessory());
                if (folder.isDirectory()) {
                    String[] fileNames = folder.list();
                    Message message = new Message("success", Message.COMMANDRETURN);
                    message.setAccessory(fileNames);
                    cmdST.writeObject(message);
                } else {
                    cmdST.writeObject(new Message("fail", Message.COMMANDRETURN, "it not a folder"));
                }
            }
        }
    }
}
